from sys import stdout, stderr


class Logger(object):
    """Log manager to facilitate the management of multiple log streams."""
    def __init__(self, enabled=True):
        self.info  = LogStream("Info")
        self.debug = LogStream("Debug",   out=stderr)
        self.warn  = LogStream("Warning", out=stderr) 
        self.error = LogStream("Error",   out=stderr)
        self.previous_state = {}
        if not enabled:
            self.disable()
            
    @property
    def enabled(self):
        return len(self.previous_state) == 0
        
    def set_enabled(self, enabled):
        (self.enable if enabled else self.disable)()
        
    def enable(self):
        for stream, enabled in self.previous_state.iteritems():
            stream.set_enabled(enabled)
        self.previous_state.clear()
        
    def disable(self):
        for stream in [self.info, self.debug, self.warn, self.error]:
            self.previous_state[stream] = stream.enabled
            stream.disable()
            
    def toggle(self):
        (self.enable if not self.enabled else self.disable)()
        
        
class LogStream(object):
    """Class implementing a simple stream of log messages written to a file. Used by the Logger
    class, a slightly more complex log manager object containing multiple log streams."""
    def __init__(self, name, out=stdout, enabled=True):
        self.name = name
        self.out = out
        self.enabled = enabled
        self.__call__ = self.do_log if enabled else self.no_log
        
    def __repr__(self):
        return "<%s(%s, %s) at 0x%08x>" % (self.__class__.__name__, self.name, 
                                           "enabled" if self.enabled else "disabled", id(self))
        
    def set_enabled(self, enabled):
        (self.enable if enabled else self.disable)()
        
    def enable(self):
        self.enabled = True
        self.__call__ = self.do_log
        
    def disable(self):
        self.enabled = False
        self.__call__ = self.no_log
        
    def toggle(self):
        (self.enable if not self.enabled else self.disable)()
        
    def do_log(self, message):
        self.out.write("[%10s] %s" % (self.name, message))
        
    def no_log(self, message):
        pass
        
        
##from sys import stdout, stderr
##from khronos.utils.misc import Switch
##from khronos.utils.textprocessing import fit, indent
##
##
##class Logger(Switch):
##    """Log manager to facilitate the manipulation of multiple log streams."""
##    RESERVED_STREAMS = set(["Info", "Default", "Debug", "Warning", "Error"])
##    
##    def __init__(self, enabled=True):
##        self.streams = dict(Info=LogStream("Info"), 
##                            Default=LogStream("Default", show_name=False), 
##                            Debug=LogStream("Debug", enabled=False), 
##                            Warning=LogStream("Warning", out=stderr), 
##                            Error=LogStream("Error", out=stderr))
##        Switch.__init__(self, enabled)
##        
##    def add_stream(self, name, show_name=True, out=stdout, enabled=True):
##        if name in self.streams:
##            raise KeyError("stream '%s' already exists in %s" % (name, self))
##        self.streams[name] = LogStream(name, show_name, out, enabled)
##        
##    def add_streams(self, names, show_name=True, out=stdout, enabled=True):
##        for name in names:
##            self.add_stream(name, show_name, out, enabled)
##            
##    def __getitem__(self, name):
##        return self.streams[name]
##        
##    def __delitem__(self, name):
##        if name in self.RESERVED_STREAMS:
##            raise ValueError("attempting to delete reserved log stream (%s)" % (name,))
##        del self.streams[name]
##        
##    def __call__(self, message, stream="Default", width=None, indent=None, newline=True):
##        if self.enabled:
##            self.streams[stream](message, width, indent, newline)
##            
##    def info(self, message, width=None, indent=None, newline=True):
##        self(message, "Info", width, indent, newline)
##        
##    def debug(self, message, width=None, indent=None, newline=True):
##        self(message, "Debug", width, indent, newline)
##        
##    def warn(self, message, width=None, indent=None, newline=True):
##        self(message, "Warning", width, indent, newline)
##        
##    def error(self, message, width=None, indent=None, newline=True):
##        self(message, "Error", width, indent, newline)
##        
##    def status(self, display=True):
##        lines = [Switch.__repr__(self)]
##        for name, stream in sorted(self.streams.iteritems()):
##            lines.append("\t%s" % (stream,))
##        status = "\n".join(lines) 
##        if display: print status
##        else:       return status
##        
##class LogStream(Switch):
##    """Class implementing a simple stream of log messages written to a file. Used by the Logger
##    class, a more complex log manager object containing multiple log streams."""
##    def __init__(self, name, show_name=True, out=stdout, enabled=True):
##        self.name = name
##        self.show_name = show_name
##        self.out = out
##        self.continuation = False
##        self._log_fnc = self._log
##        Switch.__init__(self, enabled)
##        
##    def __repr__(self):
##        return "<%s(%s, %s) at 0x%08x>" % (self.__class__.__name__, self.name, 
##                                           "enabled" if self.enabled else "disabled", id(self))
##        
##    def enable(self):
##        Switch.enable(self)
##        self._log_fnc = self._log
##        
##    def disable(self):
##        Switch.disable(self)
##        self._log_fnc = self._no_log
##        
##    def __call__(self, message, width=None, indent=None, newline=True):
##        self._log_fnc(message, width, indent, newline)
##        
##    def _log(self, message, width, indlevel, newline):
##        if not self.show_name or self.continuation:
##            message = str(message)
##        else:
##            message = "{%s} %s" % (self.name, message)
##        if indlevel is not None:
##            message = indent(message, indlevel)
##        if width is not None:
##            message = fit(message, width)
##        self.out.write(message)
##        self.continuation = not newline
##        if newline:
##            self.out.write("\n")
##            
##    def _nolog(self, message, width, indlevel, newline):
##        pass
##        